home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / SourceCode / GameKit / gamekit-1 / GKSoundStream.m < prev    next >
Text File  |  1995-06-12  |  4KB  |  121 lines

  1.  
  2. #import <gamekit/gamekit.h>
  3. #import <daymisckit/daymisckit.h>
  4. #import <soundkit/soundkit.h>
  5. #import <sound/sound.h>
  6. #import <sys/param.h>
  7.  
  8. @implementation GKSoundStream
  9.  
  10. - init
  11. { // This method should be avoided.
  12.     return [self initStreams:1];
  13. }
  14.  
  15. - initStreams:(int)nstr
  16. {
  17.     int i;
  18.     id stream, timeLeft;
  19.     if (!_initialized) [super init];
  20.     else [self freeObjects];
  21.     streamList = [[List alloc] initCount:nstr];
  22.     timeLeftList = [[List alloc] initCount:nstr];
  23.     device = [[NXSoundOut alloc] init]; // set up sound out device
  24.     for (i=0; i<nstr; i++) {
  25.     // In 3.1 need to use -initOnDevice:withParameters: to set this up
  26.     // right and remove the obsolete play method used down below. *****
  27.         stream = [[NXPlayStream alloc] initOnDevice:device];
  28.         [stream activate]; // set up our output stream
  29.         [streamList addObject:stream];
  30.         timeLeft = [[DAYTime alloc] initWithCurrentTime];
  31.         [timeLeftList addObject:timeLeft];
  32.     }
  33.     currentTime = [[DAYTime alloc] init]; // alloc here so only alloc'd once
  34.     _initialized = YES; tag = 0;
  35.     return self;
  36. }
  37.  
  38. - playSoundStruct:(SNDSoundStruct *)sound 
  39. {    // We assume proper format sounds.  Whatever object calls this one
  40.     // should assure that any SNDSoundStruct passed in is for a sound
  41.     // which is:  (1) non-fragmented, (2) 16-bit linear, (3) 22.05 kHz,
  42.     // and (4) mono.  If you don't stick to this, weird things might
  43.     // happen!!! (I don't check for any of this.  In the future, I
  44.     // probably should do so, and adjust for it. *****
  45.     int i, best = 0; // num is stream num we choose
  46.     id stream, time = [timeLeftList objectAt:best];
  47.     long timeOnStream;
  48.     // return if no data to play
  49.     if (!sound) return self;
  50.     [currentTime initWithCurrentTime];
  51.     // find the stream which will be available soonest.
  52. #ifdef NOISYDEBUG
  53.     fprintf(stderr, "GKSoundStream:  Now is: %s (%d)\n",
  54.         [currentTime stringValue], [currentTime microsecond]);
  55.     fprintf(stderr, "GKSoundStream:  Stream #%d: %s (%d)\n",
  56.         0, [time stringValue], [time microsecond]);
  57. #endif
  58.     for (i=1; i<[streamList count]; i++) {
  59.         id tempTime = [timeLeftList objectAt:i];
  60. #ifdef NOISYDEBUG
  61.     fprintf(stderr, "GKSoundStream:  Stream #%d: %s (%d)\n",
  62.         i, [tempTime stringValue], [tempTime microsecond]);
  63. #endif
  64.         if ([time isAfter:tempTime]) {
  65.             time = tempTime;
  66.             best = i;
  67.         }
  68.     }
  69.     stream = [streamList objectAt:best];
  70. #ifdef NOISYDEBUG
  71.     fprintf(stderr, "GKSoundStream:  Best time is #%d.\n", best);
  72. #endif
  73.     // enqueue the sound for playback
  74.     [stream playBuffer:(char *)sound+sound->dataLocation
  75.             size:sound->dataSize tag:tag++ channelCount:sound->channelCount
  76.             samplingRate:sound->samplingRate];
  77.     // estimate how long sound is to be on stream:
  78.     // (based on 16it 22050 Hz mono sounds.)
  79.     timeOnStream = (sound->dataSize / 2) * 45.3514739229;
  80.     // set up when stream will be finished.
  81.     if ([currentTime isAfter:time]) [time initWithCurrentTime]; // gap in play
  82.     // (above 'if' fails if stuff is on the stream right now.  Needed because
  83.     // if there was a gap in stream playback, then we start playing NOW, but
  84.     // it the stream is busy, then we start when it finishes.)  Note that
  85.     // realistically, I should add in a fudge factor if the if is true since
  86.     // the stream doesn't start to play _immediately_.  This seems to be
  87.     // close enough for my purposes, though.  Eventually, I may play with
  88.     // adding in a fudge factor to try and take this into account.  *****
  89.     // Note:  the stream delegate method - soundStream:didStartBuffer:
  90.     // might be adequate here.
  91.     [time addMicroseconds:timeOnStream];
  92. #ifdef NOISYDEBUG
  93.     fprintf(stderr, "GKSoundStream:  On stream for %ld usec.\n", timeOnStream);
  94.     fprintf(stderr, "GKSoundStream:  Estimate of time when done: %s (%d)\n\n",
  95.         [time stringValue], [time microsecond]);
  96. #endif
  97.     return time;
  98. }
  99.  
  100. - freeObjects
  101. {
  102.     [timeLeftList freeObjects];
  103.     [timeLeftList free];
  104.     [streamList freeObjects];
  105.     [streamList free];
  106.     [device free];
  107.     [currentTime free];
  108.     return self;
  109. }
  110.  
  111. - free
  112. {
  113.     [self freeObjects];
  114.     return nil;
  115. }
  116.  
  117. - streamList { return streamList; }
  118. - timeLeftList { return timeLeftList; }
  119.  
  120. @end
  121.